/********************************************************************
//      parsetree.h
//      
//      Copyright 2010 Adam Clark 
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.
**********************************************************************/

/*
 * -- Internal Housekeeping Stuff
 *    ---------------------------
 */

#define MAX_ARRAY 256

struct ArraySquares;
struct ArraySquaresList;
struct Block;
struct BreakStmt;
struct CatchClause;
struct ContinueStmt;
struct DoStmt;
struct IfStmt;
struct Expression;
struct FormalParameter;
struct ForStmt;
struct Identifier;
struct Literal;
struct ReturnStmt;
struct Statement;
struct SwitchGroup;
struct SwitchLabel;
struct SwitchStmt;
struct SynchedStmt;
struct ThrowStmt;
struct TryStmt;
struct WhileStmt;

/* ================================================================ */

/*
 * -- Literal
 *    -------
 */

typedef enum {LIT_BOOL, LIT_CHAR, LIT_STRING, LIT_SHORT, LIT_INT, 
		LIT_LONG, LIT_LONGLONG, LIT_UCHAR, LIT_USHORT, LIT_UINT, 
		LIT_ULONG, LIT_ULONGLONG, LIT_FLOAT, LIT_DOUBLE, 
		LIT_LONGDOUBLE, LIT_NULL, LIT_THIS} 
	LiteralType;
	
/* ----------------------------------------------------------------- */

typedef struct Literal {
	LiteralType literalType;
	union {
		char charVal;
		char *stringVal;
		short shortVal;
		int intVal;
		long longVal;
		long long longlongVal;
		unsigned char ucharVal;
		unsigned short ushortVal;
		unsigned int uintVal;
		unsigned long ulongVal;
		unsigned long long ulonglongVal;
		float floatVal;
		double doubleVal;
		long double longdoubleVal;
	};
} Literal;

/* ================================================================ */

/*
 * -- Names, Identifiers, Types & Arrays
 *    ----------------------------------
 */

typedef enum {id_None, id_Name, id_Super, id_This, id_Type, 
		id_Array, id_Class} IdentType;

/* ----------------------------------------------------------------- */

typedef enum {tp_None, tp_Void, tp_Named, tp_Bool, tp_Byte, 
		tp_Char, tp_Short, tp_Int, tp_Long, tp_Float, 
		tp_Double} PrimType;

/* ----------------------------------------------------------------- */

/* ===================================================================

          |                ID's                               |
          | None | Name | Super | This | Type | Array | Class |
----------+------+------+-------+------+------+-------+-------+
tp_None   |  07  |  01  |   06  |  05  |      |       |       |
----------+------+------+-------+------+------+-------+-------+
tp_Void   |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+
tp_Named  |      |      |       |      |      |   03  |   04  |
----------+------+------+-------+------+------+-------+-------+
tp_Bool   |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+
tp_Byte   |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+
tp_Char   |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+
tp_Short  |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+
tp_Int    |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+
tp_Long   |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+
tp_Float  |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+
tp_Double |      |      |       |      |  00  |   02  |       |
----------+------+------+-------+------+------+-------+-------+

00 -- Simple integral type
01 -- Simple Identifier
02 -- Array based on an integral type
03 -- Array based on a derived type
04 -- Class name (class or interface)
05 -- Pointer to 'this' class
06 -- Super of 'this'
07 -- Statement Label

<blank> -- not available

==================================================================== */

/* ----------------------------------------------------------------- */

typedef enum {ix_None, ix_Expr} IndexType;

/* ----------------------------------------------------------------- */

typedef struct ArraySquares {
	IndexType type;
	struct Expression *expr;
} ArraySquares;

/* ----------------------------------------------------------------- */

typedef struct ArraySquaresList {
	ArraySquares *curr;
	struct ArraySquaresList *next;
} ArraySquaresList;

/* ----------------------------------------------------------------- */

typedef struct Identifier {
	IdentType type;
	PrimType prim;
	char *ident;
	int numIdx;
	ArraySquares *index [MAX_ARRAY];
} Identifier;

/* ----------------------------------------------------------------- */

typedef struct FormalParameter {
	struct Expression *type;
	Identifier *ident;
	struct FormalParameter *next;
} FormalParameter;

/* ================================================================ */

/*
 * -- Modifiers
 *    ---------
 */

typedef enum {
	ML_PUBLIC = 0,
	ML_PROTECTED = 1,
	ML_PRIVATE = 2,
	ML_ABSTRACT = 3,
	ML_FINAL = 4,
	ML_STRICTFP = 5,
	ML_STATIC = 6,
	ML_NATIVE = 7,
	ML_SYNCHRONIZED = 8,
	ML_TRANSIENT = 9,
	ML_VOLATILE = 10} ModListType;
	
typedef unsigned long Modifier;

/* ================================================================ */

/*
 * -- Expressions
 *    -----------
 */

typedef enum {ex_None, ex_Literal, ex_Ident, ex_NewClass, ex_NewArray, 
		ex_Method, ex_Expr} ExprType;

/* ----------------------------------------------------------------- */

typedef struct Expression {
	ExprType leftType;
	union {
		struct Expression *leftSideExpr;
		Literal *leftSideLiteral;
		Identifier *leftSideIdent;
	}; 
	int operation;
	ExprType rightType;
	union {
		struct Expression *rightSideExpr;
		Literal *rightSideLiteral;
		Identifier *rightSideIdent;
	};
	union {
		ModListType modifiers;
		struct Expression *elsePart;
		struct Expression *argList;
	};
	struct Expression *next;
} Expression;

/* ================================================================ */

/*
 * -- Statments & Blocks
 *    ------------------
 */

typedef struct BreakStmt {
	Identifier *ident;
} BreakStmt;

/* ----------------------------------------------------------------- */

typedef struct CatchClause {
	FormalParameter *param;
	struct Block *block;
	struct CatchClause *next;
} CatchClause;

/* ----------------------------------------------------------------- */

typedef struct ContinueStmt {
	Identifier *ident;
} ContinueStmt;

/* ----------------------------------------------------------------- */

typedef struct DoStmt {
	struct Statement *stmt;
	Expression *check;
} DoStmt;

/* ----------------------------------------------------------------- */

typedef struct IfStmt {
	Expression *cond;
	struct Statement *thenPart;
	struct Statement *elsePart;
} IfStmt;

/* ----------------------------------------------------------------- */

typedef struct ForStmt {
	Expression *init;
	Expression *check;
	Expression *update;
	struct Statement *stmt;
} ForStmt;

/* ----------------------------------------------------------------- */

typedef struct ReturnStmt {
	Expression *expr;
} ReturnStmt;

/* ----------------------------------------------------------------- */

typedef struct SwitchLabel {
	Expression *label;
	struct SwitchLabel *next;
} SwitchLabel;

/* ----------------------------------------------------------------- */

typedef struct SwitchGroup {
	SwitchLabel *labels;
	struct Statement *stmt;
	struct SwitchGroup *next;
} SwitchGroup;

/* ----------------------------------------------------------------- */

typedef struct SwitchStmt {
	Expression *expr;
	SwitchGroup *groups;
} SwitchStmt;

/* ----------------------------------------------------------------- */

typedef struct SynchedStmt {
	Expression *expr;
	struct Block *block;
} SynchedStmt;

/* ----------------------------------------------------------------- */

typedef struct ThrowStmt {
	Expression *expr;
} ThrowStmt;

/* ----------------------------------------------------------------- */

typedef struct TryStmt {
	struct Block *block;
	CatchClause *catch;
	struct Block *finally;
} TryStmt;

/* ----------------------------------------------------------------- */

typedef struct WhileStmt {
	Expression *check;
	struct Statement *stmt;
} WhileStmt;

/* ----------------------------------------------------------------- */

typedef enum {st_Empty, st_Block, st_IfStmt, st_WhileStmt, st_ForStmt,
		st_ExprStmt, st_SwitchStmt, st_DoStmt, st_BreakStmt, 
		st_ContinueStmt, st_ReturnStmt, st_SynchedStmt, st_ThrowStmt,
		st_TryStmt, st_VarDecl} StatementType;

typedef struct Statement {
	StatementType type;
	Identifier *label;
	union {
		struct Block *block;
		IfStmt *ifStmt;
		WhileStmt *whileStmt;
		ForStmt *forStmt;
		Expression *exprStmt;
		SwitchStmt *switchStmt;
		DoStmt *doStmt;
		BreakStmt *breakStmt;
		ContinueStmt *continueStmt;
		ReturnStmt *returnStmt;
		SynchedStmt *synchedStmt;
		ThrowStmt *throwStmt;
		TryStmt *tryStmt;
	};
	struct Statement *next;
} Statement;

/* ----------------------------------------------------------------- */

typedef struct Block {
	Statement *stmt;
} Block;

/* ================================================================ */

/*
 * -- Packages, Imports, & Types
 *    --------------------------
 */

typedef enum {md_None, md_Abstract, md_Constructor, 
		md_Method} MethodType;

/* ----------------------------------------------------------------- */

typedef struct MethodDecl {
	Identifier *name;
	FormalParameter *params;
} MethodDecl;

/* ----------------------------------------------------------------- */

typedef struct Method {
	MethodType type;
	Modifier flags;
	Expression *retType;
	MethodDecl *decl;
	Expression *throws;
	Block *body;
} Method;

/* ----------------------------------------------------------------- */

typedef enum {cm_Empty, cm_Initializer, cm_Field, 
		cm_Method} ClassMemberType;

/* ----------------------------------------------------------------- */

typedef struct ClassMember {
	ClassMemberType type;
	union {
		Block *init;
		Expression *field;
		Method *meth;
	};
	struct ClassMember *next;
} ClassMember;

/* ----------------------------------------------------------------- */

typedef enum {td_None, td_Class, td_Interface} TypeType;

/* ----------------------------------------------------------------- */

typedef struct TypeDecl {
	TypeType type;
	Modifier flags;
	Identifier *name;
	Expression *super;
	Expression *interface;
	ClassMember *body;
	struct TypeDecl *next;
} TypeDecl;

/* ----------------------------------------------------------------- */

typedef struct CompUnit {
	Expression *pkg;
	Expression *imp;
	TypeDecl *typ;
} CompUnit;

/********************************************************************/
/********************************************************************/

/*
 * -- Literal
 *    -------
 */

Literal *MakeBoolLiteral (int l);
Literal *MakeCharLiteral (char l);
Literal *MakeStringLiteral (char *l);
Literal *MakeShortLiteral (short l);
Literal *MakeIntLiteral (int l);
Literal *MakeLongLiteral (long l);
Literal *MakeLongLongLiteral (long long l);
Literal *MakeUCharLiteral (unsigned char l);
Literal *MakeUShortLiteral (unsigned short l);
Literal *MakeUIntLiteral (unsigned int l);
Literal *MakeULongLiteral (unsigned long l);
Literal *MakeULongLongLiteral (unsigned long long l);
Literal *MakeFloatLiteral (float l);
Literal *MakeDoubleLiteral (double l);
Literal *MakeLongDoubleLiteral (long double l);
Literal *MakeNullLiteral (void);

/* ================================================================ */

/*
 * -- Names, Identifiers, & Arrays
 *    ----------------------------
 */

Identifier *NewIdentifier (IdentType t, PrimType p, char *n);
Identifier *Ident_AddArrayDefnCurr (Identifier *rv);
Identifier *Ident_AddArrayDefnCount (Identifier *rv, long n);
Identifier *Ident_AddArrayAccessCurr (Identifier *rv, Expression *e);
void Ident_SetIdentType (Identifier *n, IdentType i);
void Ident_SetPrimType (Identifier *n, PrimType p);
ArraySquaresList *AppendSquares (ArraySquaresList *rv, Expression *e);
Identifier *ConvertArraySquaresList (Identifier *rv, ArraySquaresList *l);
FormalParameter *MakeFormalParameter (Expression *t, Identifier *i);
FormalParameter *AppendFormalParameter (FormalParameter *rv, FormalParameter *n);

/* ================================================================ */

/*
 * -- Modifiers
 *    ---------
 */

Modifier Modifier_AddFlag (Modifier rv, ModListType f);

/* ================================================================ */

/*
 * -- Expressions
 *    -----------
 */

Expression *MakeExpr (int op);
Expression *Expr_SetLeftExprType (Expression *rv, ExprType t);
Expression *Expr_SetLeftExpr (Expression *rv, Expression *l);
Expression *Expr_SetLeftLiteral (Expression *rv, Literal *l);
Expression *Expr_SetLeftIdent (Expression *rv, Identifier *l);
Expression *Expr_SetRightExprType (Expression *rv, ExprType t);
Expression *Expr_SetRightExpr (Expression *rv, Expression *r);
Expression *Expr_SetRightLiteral (Expression *rv, Literal *r);
Expression *Expr_SetRightIdent (Expression *rv, Identifier *r);
Expression *Expr_AddNextExpr (Expression *rv, Expression *n);
Expression *Expr_SetArgList (Expression *rv, Expression *a);
Expression *Expr_SetLeftType (Expression *rv, ExprType t);
Expression *Expr_SetRightType (Expression *rv, ExprType t);
Expression *Expr_AddThenElse (Expression *rv, Expression *t, Expression *e);
Expression *Expr_SetOp (Expression *rv, int op);
Expression *Expr_SetIdentTypeLeft (Expression *n, IdentType i);
Expression *Expr_SetPrimTypeLeft (Expression *n, PrimType p);
Expression *Expr_SetIdentTypeRight (Expression *n, IdentType i);
Expression *Expr_SetPrimTypeRight (Expression *n, PrimType p);
Expression *Expr_SetModifiers (Expression *rv, Modifier m);

/* ================================================================ */

/*
 * -- Statments & Blocks
 *    ------------------
 */

Block *MakeBlock (Statement *s);
BreakStmt *MakeBreakStmt (Identifier *i);
CatchClause *MakeCatchClause (FormalParameter *p, Block *b);
ContinueStmt *MakeContinueStmt (Identifier *i);
DoStmt *MakeDoStmt (Statement *s, Expression *c);
IfStmt *MakeIfStmt (Expression *c, Statement *t, Statement *e);
ForStmt *MakeForStmt (Expression *i, Expression *c, Expression *u, Statement *s);
ReturnStmt *MakeReturnStmt (Expression *e);
SwitchGroup *MakeSwitchGroup (SwitchLabel *l, Statement *s);
SwitchStmt *MakeSwitchStmt (Expression *e, SwitchGroup *g);
SynchedStmt *MakeSynchedStmt (Expression *e, Block *b);
ThrowStmt *MakeThrowStmt (Expression *e);
TryStmt *MakeTryStmt (Block *b, CatchClause *c, Block *f);
WhileStmt *MakeWhileStmt (Expression *c, Statement *s);

CatchClause *AppendCatchClause (CatchClause *rv, CatchClause *c);
SwitchGroup *AppendSwitchGroup (SwitchGroup *rv, SwitchGroup *n);
SwitchLabel *AppendSwitchLabel (SwitchLabel *rv, Expression *l);

Statement *MakeStmt (void);
Statement *Stmt_SetNextStmt (Statement *rv, Statement *n);
Statement *Stmt_SetLabel (Statement *rv, Identifier *l);
Statement *Stmt_SetBlockStmt (Statement *rv, Block *b);
Statement *Stmt_SetBreakStmt (Statement *rv, BreakStmt *b);
Statement *Stmt_SetContinueStmt (Statement *rv, ContinueStmt *c);
Statement *Stmt_SetIfStmt (Statement *rv, IfStmt *i);
Statement *Stmt_SetDoStmt (Statement *rv, DoStmt *d);
Statement *Stmt_SetExprStmt (Statement *rv, Expression *e);
Statement *Stmt_SetForStmt (Statement *rv, ForStmt *f);
Statement *Stmt_SetReturnStmt (Statement *rv, ReturnStmt *r);
Statement *Stmt_SetSwitchStmt (Statement *rv, SwitchStmt *s);
Statement *Stmt_SetSynchedStmt (Statement *rv, SynchedStmt *s);
Statement *Stmt_SetThrowStmt (Statement *rv, ThrowStmt *t);
Statement *Stmt_SetTryStmt (Statement *rv, TryStmt *t);
Statement *Stmt_SetWhileStmt (Statement *rv, WhileStmt *w);
Statement *Stmt_SetVarDeclStmt (Statement *rv, Expression *v);

/* ================================================================ */

/*
 * -- Packages, Imports, & Types
 *    --------------------------
 */

MethodDecl *MakeMethodDecl(Identifier *i, FormalParameter *p);
Method *MakeMethod(MethodType tp, Modifier m, Expression *r, 
		MethodDecl *d, Expression *t);
Method *Meth_SetBody (Method *rv, Block *b);
Method *Meth_SetType (Method *rv, MethodType t);
MethodDecl *MethD_AddArraySquares (MethodDecl *rv);

ClassMember *MakeEmptyClassMember(void);
ClassMember *cmbr_SetField (ClassMember *rv, Expression *f);
ClassMember *cmbr_SetMethod (ClassMember *rv, Method *m);
ClassMember *cmbr_SetInitializer (ClassMember *rv, Block *b);
ClassMember *cmbr_SetNextCMbr (ClassMember *rv, ClassMember *n);

TypeDecl *MakeEmptyTypeDecl (void);
TypeDecl *Type_SetClass (TypeDecl *rv, Modifier m, Identifier *i, 
		Expression *s, Expression *f, ClassMember *b);
TypeDecl *Type_SetInterface (TypeDecl *rv, Modifier m, Identifier *i, 
		Expression *f, ClassMember *b);
TypeDecl *Type_SetNextTypeDecl (TypeDecl *rv, TypeDecl *n);

CompUnit *MakeCompUnit (Expression *p, Expression *i, TypeDecl *t);

/*******************************************************************/
